using System;
using System.Collections.Generic;
using System.Text;
using System.ServiceModel;
using Microsoft.Practices.CompositeUI;
using Microsoft.Practices.CompositeUI.SmartParts;
using Metro.SmartClient.Infrastructure.Interface.NotificationService;
using Microsoft.Practices.CompositeUI.EventBroker;
using Metro.SmartClient.Infrastructure.Interface.Constants;
using Microsoft.Practices.ObjectBuilder;

namespace Metro.SmartClient.Infrastructure.Interface
{
    public class ServiceClient: WorkItemController
    {
        private WorkItem workItem;
        private NotificationClient client;
        private ServiceCallback serviceCallback;
        
        [CreateNew]
        public ServiceCallback Callback
        {
            set
            {
                serviceCallback = value;
            }
        }

        public class ServiceCallback : INotificationCallback
        {
            [EventPublication(EventTopicNames.NewOrderEvent, PublicationScope.Global)]
            public event EventHandler<EventArgs<Metro.Admin.BusinessEntities.Order>> NewOrderEvent;
            [EventPublication(EventTopicNames.DeleteOrderEvent, PublicationScope.Global)]
            public event EventHandler<EventArgs<Metro.Admin.BusinessEntities.Order>> DeleteOrderEvent;
            [EventPublication(EventTopicNames.UpdateOrderEvent, PublicationScope.Global)]
            public event EventHandler<EventArgs<Metro.Admin.BusinessEntities.Order>> UpdateOrderEvent;
            [EventPublication(EventTopicNames.NewTransactionsEvent, PublicationScope.Global)]
            public event EventHandler<EventArgs<List<Metro.Admin.BusinessEntities.Transaction>>> NewTransactionsEvent;
            [EventPublication(EventTopicNames.DeleteTransactionsEvent, PublicationScope.Global)]
            public event EventHandler<EventArgs<List<Metro.Admin.BusinessEntities.Transaction>>> DeleteTransactionsEvent;
            [EventPublication(EventTopicNames.AskDeleteTransaction, PublicationScope.Global)]
            public event EventHandler<EventArgs<List<Metro.Admin.BusinessEntities.Transaction>>> AskDeleteTransactionEvent;
            [EventPublication(EventTopicNames.RejectDeleteTransaction, PublicationScope.Global)]
            public event EventHandler<EventArgs<List<Metro.Admin.BusinessEntities.Transaction>>> RejectDeleteTransactionEvent;
            [EventPublication(EventTopicNames.ParameterUpdateEvent, PublicationScope.Global)]
            public event EventHandler<EventArgs<List<Metro.Admin.BusinessEntities.Parameter>>> ParameterUpdateEvent;
            [EventPublication(EventTopicNames.StatsUpdate, PublicationScope.Global)]
            public event EventHandler<EventArgs<Metro.Admin.BusinessEntities.Stats>> StatsUpdate;

            #region INotificationCallback Members
            public void OrderChange(Metro.Admin.BusinessEntities.OrderOperation operation, Metro.Admin.BusinessEntities.Order order)
            {
                try
                {
                    switch (operation)
                    {
                        case Metro.Admin.BusinessEntities.OrderOperation.New:
                            OnNewOrderEvent(new EventArgs<Metro.Admin.BusinessEntities.Order>(order));
                            break;
                        case Metro.Admin.BusinessEntities.OrderOperation.Update:
                            OnUpdateOrderEvent(new EventArgs<Metro.Admin.BusinessEntities.Order>(order));
                            break;
                        case Metro.Admin.BusinessEntities.OrderOperation.Delete:
                            OnDeleteOrderEvent(new EventArgs<Metro.Admin.BusinessEntities.Order>(order));
                            break;
                            
                    }
                }
                catch (Exception ex)
                {
                    throw ex;
                }
            }

            public void TransactionsChange(Metro.Admin.BusinessEntities.TransaccionOperation operation, List<Metro.Admin.BusinessEntities.Transaction> transactions)
            {
                try
                {
                    switch (operation)
                    {
                        case Metro.Admin.BusinessEntities.TransaccionOperation.New:
                            OnNewTransactionsEvent(new EventArgs<List<Metro.Admin.BusinessEntities.Transaction>>(transactions));
                            break;
                        case Metro.Admin.BusinessEntities.TransaccionOperation.Delete:
                            OnDeleteTransactionsEvent(new EventArgs<List<Metro.Admin.BusinessEntities.Transaction>>(transactions));
                            break;
                        case Metro.Admin.BusinessEntities.TransaccionOperation.AskDelete:
                            OnAskDeleteTransactionEvent(new EventArgs<List<Metro.Admin.BusinessEntities.Transaction>>(transactions));
                                break;
                        case Metro.Admin.BusinessEntities.TransaccionOperation.Reject:
                            OnRejectDeleteTransactionEvent(new EventArgs<List<Metro.Admin.BusinessEntities.Transaction>>(transactions));
                                break;
                    }
                }
                catch (Exception ex)
                {
                    throw ex;
                }
            }

            public void ParameterChange(List<Metro.Admin.BusinessEntities.Parameter> parameterList)
            {
                try
                {
                    OnParametersUpdateEvent(new EventArgs<List<Metro.Admin.BusinessEntities.Parameter>>(parameterList)); 
                }
                catch (Exception ex)
                {
                    throw ex;
                }
            }

            public void StatsChange(Metro.Admin.BusinessEntities.Stats stats)
            {
                try
                {
                    OnStatsUpdate(new EventArgs<Metro.Admin.BusinessEntities.Stats>(stats)); 
                }
                catch (Exception ex)
                {
                    
                    throw ex;
                }
            
            }

            #endregion

            public virtual void OnNewTransactionsEvent(EventArgs<List<Metro.Admin.BusinessEntities.Transaction>> eventArgs)
            {
                if (NewTransactionsEvent != null)
                {
                    NewTransactionsEvent(this, eventArgs);
                }
            }

            public virtual void OnDeleteTransactionsEvent(EventArgs<List<Metro.Admin.BusinessEntities.Transaction>> eventArgs)
            {
                if (DeleteTransactionsEvent != null)
                {
                    DeleteTransactionsEvent(this, eventArgs);
                }
            }

            public virtual void OnAskDeleteTransactionEvent(EventArgs<List<Metro.Admin.BusinessEntities.Transaction>> eventArgs)
            {
                if (AskDeleteTransactionEvent != null)
                {
                    AskDeleteTransactionEvent(this, eventArgs);
                }
            }

            public virtual void OnRejectDeleteTransactionEvent(EventArgs<List<Metro.Admin.BusinessEntities.Transaction>> eventArgs)
            {
                if (RejectDeleteTransactionEvent != null)
                {
                    RejectDeleteTransactionEvent(this, eventArgs);
                }
            }

            public virtual void OnNewOrderEvent(EventArgs<Metro.Admin.BusinessEntities.Order> eventArgs)
            {
                if (NewOrderEvent != null)
                {
                    NewOrderEvent(this, eventArgs);
                }
            }

            public virtual void OnDeleteOrderEvent(EventArgs<Metro.Admin.BusinessEntities.Order> eventArgs)
            {
                if (DeleteOrderEvent != null)
                {
                    DeleteOrderEvent(this, eventArgs);
                }
            }

            public virtual void OnUpdateOrderEvent(EventArgs<Metro.Admin.BusinessEntities.Order> eventArgs)
            {
                if (UpdateOrderEvent != null)
                {
                    UpdateOrderEvent(this, eventArgs);
                }
            }

            public virtual void OnParametersUpdateEvent(EventArgs<List<Metro.Admin.BusinessEntities.Parameter>> eventArgs)
            {
                if (ParameterUpdateEvent != null)
                {
                    ParameterUpdateEvent(this, eventArgs);
                }
            }

            public virtual void OnStatsUpdate(EventArgs<Metro.Admin.BusinessEntities.Stats> eventArgs)
            {
                if (StatsUpdate != null)
                {
                    StatsUpdate(this, eventArgs);
                }
            }
        }

        [InjectionConstructor]
        public ServiceClient([ServiceDependency] WorkItem rootWorkItem) 
        {
            this.workItem = rootWorkItem; 
        }

        public void Link()
        {
            try
            {
                InstanceContext context = new InstanceContext(this.serviceCallback);
                client = new NotificationClient(context);
                client.Subscribe();
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public void UnLink()
        {
            try
            {
                client.Unsubscribe();
                client.Close();
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public void PublishOrderChange(Metro.Admin.BusinessEntities.OrderOperation operation, Metro.Admin.BusinessEntities.Order order)
        {
            try
            {
                client.PublishOrderChange(operation, order);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public void PublishTransactionsChange(Metro.Admin.BusinessEntities.TransaccionOperation operation, List<Metro.Admin.BusinessEntities.Transaction> transactions)
        {
            try
            {
                client.PublishTransactionsChange(operation, transactions);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public void PublishParameterChange(List<Metro.Admin.BusinessEntities.Parameter> parameterList)
        {
            try
            {
                client.PublishParameterChange(parameterList);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
    
    }
}